Skip to content

IECoreUSD : Round-trip Material prims with binds.#1521

Open
boberfly wants to merge 1 commit intoImageEngine:mainfrom
boberfly:feature/materialBindRoundtrip
Open

IECoreUSD : Round-trip Material prims with binds.#1521
boberfly wants to merge 1 commit intoImageEngine:mainfrom
boberfly:feature/materialBindRoundtrip

Conversation

@boberfly
Copy link
Contributor

@boberfly boberfly commented Feb 25, 2026

Generally describe what this PR will do, and why it is needed.

  • Normally when saving and loading ShaderNetwork combinations on locations, a materials/material_<hash> child on the location itself gets created of schema-types UsdGeomScope container with a UsdShadeMaterial inside and metadata cortex_autoMaterials on the container to inform IECoreUSD to not translate this back to path/prims when loading back the USD scene into Gaffer.
  • This works correctly for round-trips in Gaffer itself, however to match what other DCCs are doing you usually have a scene location of a material, and use a material bind to reference the material from another location in the scene and expect to round-trip this into another DCC without the material location changing.
  • This PR allows you be explicit in setting a location via the usd:schemaType string attribute to either Scope or Material and assign Gaffer ShaderNetworks to this location, and by using usd:material:binding string attribute on the destination shader assignment location of the path to the material location, will correctly do the binding when saving out the USD file, as well as preserving this form when loading back into Gaffer. This also works for usd:material:binding:full and usd:material:binding:preview which corresponds to USD's purpose functionality for material binding.
  • If the destination location has both a binding attribute and a ShaderNetwork combination assigned, when saving out the USD scene, there is an attempt to detect if the ShaderNetwork combination matches and will omit saving out the normal way of creating a child unique material on the location and instead do a direct reference bind to the material location. If they don't match eg. the location has a ShaderTweaks modifying the ShaderNetwork, then it saves out exactly as before to preserve the unique changes on that location.
  • Gaffer doesn't have ShaderNetwork referencing natively, but with CopyAttributes this can be emulated (I do this with 2 "Extension" nodes with one node that defines the Material and location of where it'll go and sets usd:schemaType for the hierarchy, as well as some ShaderAssignment node plugs promoted - and a MaterialAssign node that uses CopyAttributes and can set the purpose of the copy and create the usd:material:binding* attribute inside).
  • An "adapter" could work for a nice follow-up to automate this more I'd imagine, much like how the adapters work for instancing in Gaffer.
  • A __materials set is created much like the __lights set. This is unused at the moment and could be removed from this PR but it could come in-handy at a later stage. I am thinking of this place here is a little fragile and would be best to check if the location is a part of __materials.https://github.com/boberfly/cortex/blob/afb46d5a69a382be806e0d0c5567cea8a7777505/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp#L1665

Related Issues

  • N/A

Dependencies

  • N/A

Breaking Changes

  • usd:material:binding attributes will now get created onto locations with material binding, as well as the usd:schemaType attribute for only UsdGeomScope and UsdShadeMaterial prims when loading in. There was care in making sure the pure Gaffer workflow/roundtrip isn't affected at all with the cortex_autoMaterials = true metadata, this would be a change for reading in USDs that are made in other DCCs.
  • I had to add a few cortex_autoMaterials = true to unit-test .usda 's which are mostly harmless, it helps to not litter the existing checks with additional attributes that the asserts don't account for...
  • This isn't done yet but I'm thinking about reliably removing the Xform data from Scope/Materials could be a potential breaking change, but left alone for now.

Checklist

  • I have read the contribution guidelines.
  • I have updated the documentation, if applicable.
  • I have tested my change(s) in the test suite, and added new test cases where necessary.
  • My code follows the Cortex project's prevailing coding style and conventions.

@boberfly
Copy link
Contributor Author

Just to add I know this change is a little flaky for workflows as Gaffer isn't doing referencing from material locations natively, I'm open for ideas on how to improve the approach and was thinking the adapter stuff might work out.

This approach benefits more of a pipeline with many DCCs passing materials between them and having the ability to load and save materials mostly consistently between them.

@boberfly boberfly force-pushed the feature/materialBindRoundtrip branch from afb46d5 to 2a34c90 Compare February 25, 2026 05:54
@johnhaddon
Copy link
Member

Thanks Alex. While I understand the motivation here, and am glad that this is useful for your workflow, we'll be holding off on looking at this in any detail until such a time as we can consider end-to-end support for this style of material binding natively in Gaffer. While I don't rule out adopting the USD style because it does have its benefits, there are also benefits to Gaffer's methodology, and we need to manage any transition (or coexistence) carefully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants